package com.ease.framework.gef4p.actions {
   import com.ease.util.collections.HashMap;
   import com.ease.util.collections.Map;
   import com.ease.component.managers.DepthManager;
   import com.ease.framework.assets.icons.align.AlignIconFactory;
   import com.ease.framework.gef.IEditor;
   import com.ease.framework.gef.ui.ISelection;
   import com.ease.framework.gef.ui.SelectionManager;
   import com.ease.framework.gef4g.GraphicalViewport;
   import com.ease.framework.gef4g.IGraphicalEditor;
   import com.ease.framework.gef4p.figures.INodeFigure;
   import com.ease.framework.gef4p.viewers.DiagramGraphicalViewerControl;
   import com.ease.framework.layers.Layer;
   import com.ease.framework.workbench.Workbench;

   import flash.display.DisplayObject;
   import flash.events.MouseEvent;
   import flash.geom.Point;

   import mx.controls.Menu;
   import mx.controls.PopUpButton;
   import mx.core.UIComponent;
   import mx.events.DropdownEvent;
   import mx.events.FlexEvent;
   import mx.events.MenuEvent;

   public class AlignButton extends PopUpButton {
      private var menuCompAlign:Menu;

      private var enabledIcons:Map = new HashMap();
      private var disabledIcons:Map = new HashMap();

      //当前的，每次打开都需要重新获取当前editor的.
      private var sm:SelectionManager;

      private var currentContentLayer:Layer;

      private var _currentAlign:String;

      private var _xmlData:XML;

      public function AlignButton() {
         super();
         addEventListener(FlexEvent.CREATION_COMPLETE, initBtnCompAlign);
         addEventListener(DropdownEvent.OPEN, btnCompAlignOpen);
         addEventListener(MouseEvent.CLICK, onClick);

         setStyle("icon", AlignIconFactory.compAlign);

         enabledIcons.put("alignLeft", AlignIconFactory.compAlignLeft);
         enabledIcons.put("alignRight", AlignIconFactory.compAlignRight);
         enabledIcons.put("alignCenter", AlignIconFactory.compAlignCenter);
         enabledIcons.put("alignTop", AlignIconFactory.compAlignTop);
         enabledIcons.put("alignBottom", AlignIconFactory.compAlignBottom);
         enabledIcons.put("alignMiddle", AlignIconFactory.compAlignMiddle);
         enabledIcons.put("spaceH", AlignIconFactory.compSpaceH);
         enabledIcons.put("spaceV", AlignIconFactory.compSpaceV);
         enabledIcons.put("toTop", AlignIconFactory.iconToTop);
         enabledIcons.put("toBottom", AlignIconFactory.iconToBottom);
         enabledIcons.put("oneLayerUp", AlignIconFactory.iconOneLayerUp);
         enabledIcons.put("oneLayerDown", AlignIconFactory.iconOneLayerDown);

         disabledIcons.put("alignLeft", AlignIconFactory.compAlignLeft_d);
         disabledIcons.put("alignRight", AlignIconFactory.compAlignRight_d);
         disabledIcons.put("alignCenter", AlignIconFactory.compAlignCenter_d);
         disabledIcons.put("alignTop", AlignIconFactory.compAlignTop_d);
         disabledIcons.put("alignBottom", AlignIconFactory.compAlignBottom_d);
         disabledIcons.put("alignMiddle", AlignIconFactory.compAlignMiddle_d);
         disabledIcons.put("spaceH", AlignIconFactory.compSpaceH_d);
         disabledIcons.put("spaceV", AlignIconFactory.compSpaceV_d);
         disabledIcons.put("toTop", AlignIconFactory.iconToTop_d);
         disabledIcons.put("toBottom", AlignIconFactory.iconToBottom_d);
         disabledIcons.put("oneLayerUp", AlignIconFactory.iconOneLayerUp_d);
         disabledIcons.put("oneLayerDown", AlignIconFactory.iconOneLayerDown_d);

         xmlData = AlignMenuData.xml;

      }

      protected function initBtnCompAlign(event:FlexEvent):void {
         menuCompAlign = Menu.createMenu(null, xmlData, false);
         menuCompAlign.labelField = "@label";
         menuCompAlign.iconFunction = menuCompAlignIconFunction;
         menuCompAlign.setStyle("textAlign", "left");
         menuCompAlign.addEventListener(MenuEvent.ITEM_CLICK, alignItemClicked);
         popUp = menuCompAlign;

      }

      protected function btnCompAlignOpen(event:DropdownEvent):void {

         var enableAlign:Boolean = (sm.numSelected > 1);
         var enableSpace:Boolean = (sm.numSelected > 2);

         var list:XMLList = AlignMenuData.xml.children();
         for (var i:int = 0; i < list.length(); i++) {
            var item:XML = list[i];
            var id:String = item.@id;
            switch (id) {
               case "alignLeft":
               case "alignRight":
               case "alignCenter":
               case "alignTop":
               case "alignBottom":
               case "alignMiddle":
                  item.@enabled = enableAlign;
                  break;
               case "spaceH":
               case "spaceV":
                  item.@enabled = enableSpace;
                  break;
               case "toTop":
               case "toBottom":
               case "oneLayerUp":
               case "oneLayerDown":
                  item.@enabled = (sm.numSelected > 0);
                  break;
            }
         }
      }

      private function menuCompAlignIconFunction(obj:Object):Class {
         var menuItem:XML = obj as XML;
         var id:String = menuItem.@id;

         sm = IEditor(Workbench.instance.currentEditor).getEditDomain().getSelectionManager();

         var enableAlign:Boolean = (sm.numSelected > 1);
         var enableSpace:Boolean = (sm.numSelected > 2);

         var enable:Boolean = true;

         switch (id) {
            case "alignLeft":
            case "alignRight":
            case "alignCenter":
            case "alignTop":
            case "alignBottom":
            case "alignMiddle":
               enable = enableAlign;
               break;
            case "spaceH":
            case "spaceV":
               enable = enableSpace;
               break;
            case "toTop":
            case "toBottom":
            case "oneLayerUp":
            case "oneLayerDown":
               enable = (sm.numSelected > 0);
               break;
         }

         if (enable) {
            return enabledIcons.getObject(id) as Class;
         }
         else {
            return disabledIcons.getObject(id) as Class;
         }

         return null;
      }

      //=======================================
      // 于Align操作相关的一些变量.
      //=======================================
      private var max:Number;
      private var min:Number;

      protected function alignItemClicked(event:MenuEvent):void {
         sm = IEditor(Workbench.instance.currentEditor).getEditDomain().getSelectionManager();
         currentContentLayer = GraphicalViewport(IGraphicalEditor(Workbench.instance.currentEditor).getGraphicalViewer().getViewport()).contentLayer;

         var menuItem:XML = event.item as XML;
         var id:String = menuItem.@id;

         handleAlign(id);

         currentAlign = id;

         setStyle("icon", enabledIcons.getObject(id) as Class);
      }

      protected function onClick(event:MouseEvent):void {
         if (sm == null)
            sm = IEditor(Workbench.instance.currentEditor).getEditDomain().getSelectionManager();

         if (currentAlign)
            handleAlign(currentAlign);
         else
            this.open();
      }

      private function handleAlign(id:String):void {
         if (id == "alignLeft") {
            handleAlignLeft();
         }
         else if (id == "alignRight") {
            handleAlignRight();
         }
         else if (id == "alignCenter") {
            handleAlignCenter();
         }
         else if (id == "alignTop") {
            handleAlignTop();
         }
         else if (id == "alignBottom") {
            handleAlignBottom();
         }
         else if (id == "alignMiddle") {
            handleAlignMiddle();
         }
         else if (id == "toTop") {
            handleToTop();
         }
         else if (id == "toBottom") {
            handleToBottom();
         }
         else if (id == "oneLayerUp") {
            handleOneLayerUp();
         }
         else if (id == "oneLayerDown") {
            handleOneLayerDown();
         }
      }

      private function handleAlignLeft():void {
         min = int.MAX_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               min = Math.min(min, UIComponent(ifs).localToGlobal(new Point(0, 0)).x);
            }
         }

         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).x = UIComponent(ifs).parent.globalToLocal(new Point(min, 0)).x;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);

      }

      private function handleAlignRight():void {
         max = int.MIN_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               max = Math.max(max, (UIComponent(ifs).localToGlobal(new Point(0, 0)).x + UIComponent(ifs).width));
            }
         }
         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).x = UIComponent(ifs).parent.globalToLocal(new Point(max, 0)).x - UIComponent(ifs).width;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);
      }

      private function handleAlignCenter():void {
         max = int.MIN_VALUE;
         min = int.MAX_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               max = Math.max(max, (UIComponent(ifs).localToGlobal(new Point(0, 0)).x + UIComponent(ifs).width / 2));
               min = Math.min(min, (UIComponent(ifs).localToGlobal(new Point(0, 0)).x + UIComponent(ifs).width / 2));
            }
         }
         var centerX:Number = (max + min) / 2;
         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).x = UIComponent(ifs).parent.globalToLocal(new Point(centerX, 0)).x - UIComponent(ifs).width / 2;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);

      }

      private function handleAlignTop():void {
         min = int.MAX_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               min = Math.min(min, UIComponent(ifs).localToGlobal(new Point(0, 0)).y);
            }
         }

         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).y = UIComponent(ifs).parent.globalToLocal(new Point(0, min)).y;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);
      }

      private function handleAlignBottom():void {
         max = int.MIN_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               max = Math.max(max, (UIComponent(ifs).localToGlobal(new Point(0, 0)).y + UIComponent(ifs).height));
            }
         }

         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).y = UIComponent(ifs).parent.globalToLocal(new Point(0, max)).y - UIComponent(ifs).height;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);
      }

      private function handleAlignMiddle():void {
         min = int.MAX_VALUE;
         max = int.MIN_VALUE;
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               min = Math.min(min, (UIComponent(ifs).localToGlobal(new Point(0, 0)).y + UIComponent(ifs).height / 2));
               max = Math.max(max, (UIComponent(ifs).localToGlobal(new Point(0, 0)).y + UIComponent(ifs).height / 2));
            }
         }

         var centerY:Number = (max + min) / 2;
         var movedNodes:Array = new Array();
         for each (ifs in sm.selecteds) {
            if (ifs is INodeFigure) {
               INodeFigure(ifs).y = UIComponent(ifs).parent.globalToLocal(new Point(0, centerY)).y - UIComponent(ifs).height / 2;
               movedNodes.push(ifs);
            }
         }
         handleMoveNodes(movedNodes);
      }

      private function handleToTop():void {
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               DepthManager.bringToTop(ifs as DisplayObject);
            }
         }
      }

      private function handleToBottom():void {
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               DepthManager.bringToBottom(ifs as DisplayObject);
            }
         }
      }

      private function handleOneLayerUp():void {
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               DepthManager.bringUp(ifs as DisplayObject);
            }
         }
      }

      private function handleOneLayerDown():void {
         for each (var ifs:ISelection in sm.selecteds) {
            if (ifs is INodeFigure) {
               DepthManager.bringDown(ifs as DisplayObject);
            }
         }
      }

      private function handleMoveNodes(nodes:Array):void {
         DiagramGraphicalViewerControl(IGraphicalEditor(Workbench.instance.currentEditor).getGraphicalViewer().getControl()).handleMoveNodes(nodes);
      }

      public function get xmlData():XML {
         return _xmlData;
      }

      public function set xmlData(value:XML):void {
         _xmlData = value;
      }

      public function get currentAlign():String {
         return _currentAlign;
      }

      public function set currentAlign(value:String):void {
         _currentAlign = value;
      }

   }
}